package server.listener;

import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.minlog.Log;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.imageio.ImageIO;
import server.ServerManager;
import util.Client;
import util.Screenshot;

public class ServerListener extends Listener {

    private ServerManager server;

    public ServerListener(ServerManager server) {
        this.server = server;
    }

    @Override
    public void received(Connection connection, Object object) {
        if (object instanceof net.packet.Connect) {

            net.packet.Connect packet = (net.packet.Connect) object;

            Client client = new Client(connection);

            client.version = packet.version;
            client.ipExternal = packet.ipExternal;
            client.ipInternal = packet.ipInternal;
            client.osName = packet.osName;
            client.osVersion = packet.osVersion;
            client.osArchitecture = packet.osArchitecture;
            client.username = packet.username;
            client.hostname = packet.hostname;
            client.javaVersion = packet.javaVersion;
            client.tempDirectory = packet.tempDirectory;
            client.desktopDirectory = packet.desktopDirectory;
            client.userDirectory = packet.userDirectory;
            client.systemDirectory = packet.systemDirectory;
            
            server.getClientManager().addClient(client);
            server.updateClients();

            server.writeToLog(Log.LEVEL_INFO, String.format("Client %s connected", client));

        } else if (object instanceof net.packet.Command) {

            net.packet.Command packet = (net.packet.Command) object;

            server.getClientFromConnection(connection).getClientControl().updateCommandResponse(packet.response);

        } else if (object instanceof net.packet.Screenshot) {

            net.packet.Screenshot packet = (net.packet.Screenshot) object;

            try {
                BufferedImage image = Screenshot.convertToBufferedImage(packet.image);

                File file = new File(server.getClientFromConnection(connection).getClientControl().getScreenshotSaveTo());

                ImageIO.write(image, "jpg", file);
            } catch (FileNotFoundException ex) {
                server.writeToLog(Log.LEVEL_ERROR, "[Screenshot] Could not find given path", ex);
            } catch (IOException ex) {
                server.writeToLog(Log.LEVEL_ERROR, "[Screenshot] Failed to save file", ex);
            }

        } else if (object instanceof net.packet.CDDrive) {

            net.packet.CDDrive packet = (net.packet.CDDrive) object;

            if (packet.getDrive) {
                server.getClientFromConnection(connection).getClientControl().updateCDDriveInformation(packet.response);
            } else {
                server.getClientFromConnection(connection).getClientControl().updateCDDriveResponse(packet.response);
            }

        } else if (object instanceof net.packet.RemoteDesktopFrame) {

            net.packet.RemoteDesktopFrame packet = (net.packet.RemoteDesktopFrame) object;

            server.getClientFromConnection(connection).getClientRemoteDesktop().updateImage(packet.image);

        } else if (object instanceof net.packet.Idle) {

            net.packet.Idle packet = (net.packet.Idle) object;

            server.getClientManager().getClientFromConnection(connection).idling = packet.idling;
            server.getClientTableModel().fireTableDataChanged();

        } else if (object instanceof net.packet.TaskList) {

            net.packet.TaskList packet = (net.packet.TaskList) object;

            server.getClientFromConnection(connection).getClientControl().refrehTaskList(packet.tasks);

        } else if (object instanceof net.packet.TaskKill) {

            net.packet.TaskKill packet = (net.packet.TaskKill) object;

            server.getClientFromConnection(connection).getClientControl().updateTaskKillResponse(packet.response);

        } else if (object instanceof net.packet.Log) {

            net.packet.Log packet = (net.packet.Log) object;

            server.writeToLog(packet.type, packet.text);

        } else if (object instanceof net.packet.FileDownload) {

            net.packet.FileDownload packet = (net.packet.FileDownload) object;

            server.getClientFromConnection(connection).getClientControl().updateFileDownloadProgress(packet.receivedBytes, packet.fileSize, packet.downloadSpeed);

        }
    }

    @Override
    public void disconnected(Connection connection) {
        Client client = server.getClientFromConnection(connection);

        // Close client windows
        if (client.getClientControl() != null) {
            client.getClientControl().setVisible(false);
        }
        
        if (client.getClientRemoteDesktop() != null) {
            client.getClientRemoteDesktop().setVisible(false);
        }

        server.writeToLog(Log.LEVEL_INFO, String.format("Client %s disconnected", client));

        server.getClientManager().removeClient(client);
        server.updateClients();
        connection.close();
    }

}
